﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xant.FlowEngine.Core;
using Xant.FlowEngine.Factory;
using Dapper;
using System.Data;

namespace Xant.FlowEngine.Serialize
{
    public sealed class DefaultSerializer : AbstractSerializer
    {
        public override T Load<T>(IDbConnection conn, int id, ref bool handled)
        {
            return base.Load<T>(conn, id, ref handled);
        }

        public override void Insert<T>(IDbTransaction trans, T item, ref bool handled)
        {
            string sql;
            Type type = item.GetType();

            /*if (type==typeof(MainProcess) || type==typeof(ProcessInstance))//流程实例
            {
                base.Insert<T>(trans, item, ref handled);
                handled = true;
            }*/
            if (type==typeof(EmailActivity))//邮件活动
            {
                //先调用基类的Insert方法
                base.Insert<T>(trans, item, ref handled);
                //再将邮件活动类特有的属性保存到数据库中
                var activity = item as EmailActivity;
                sql = "INSERT INTO xfEmailActivity(Id, Recipients, Subject, Content) VALUES(@id, @Recipients, @Subject, @Content)";
                trans.Connection.Execute(sql, activity, trans);
                handled = true;
            }
            else if(type==typeof(WorkActivity))//工作活动
            {
                //先调用基类的Insert方法
                base.Insert<T>(trans, item, ref handled);
                //再将当前活动类特有的属性保存到数据库中
                var activity = item as WorkActivity;
                sql = string.Format("INSERT INTO xfWorkActivity(Id, Performers, Notifiers) VALUES('{0}', '{1}', '{2}')", 
                    activity.Id, "", "");
                trans.Connection.Execute(sql, activity, trans);
                SerializerManager.Save(trans, activity.Workitems.ToArray());
                handled = true;
            }
            else if(type==typeof(Workitem))//工作项
            {
                //先调用基类的Insert方法
                base.Insert<T>(trans, item, ref handled);
                //再将当前活动类特有的属性保存到数据库中
                var workitem = item as Workitem;
                if (item.RowVersion == 0)
                {
                    //item.Id = trans.GenerateKey("Workitem");
                }
                //为防止数据不一致，在新增记录到数据库时，将RowVersion字段固定赋值为1，而不从对象中直接获取属性，在插入成功后再将对象RowVersion属性值设为1
                sql = "INSERT INTO xfWorkitem(Id, ActivityId, Readonly, Action, EntryTime, LeaveTime, Invalid, RowVersion) VALUES(@Id, @ActivityId, @Readonly, @Action, @EntryTime, @LeaveTime, @Invalid, 1)";
                trans.Connection.Execute(sql, workitem, trans);
                workitem.RowVersion = 1;
                handled = true;
            }
            else if(type==typeof(Transition))//流程迁转
            {
                //先调用基类的Insert方法
                base.Insert<T>(trans, item, ref handled);
                //再将当前活动类特有的属性保存到数据库中
                var transition = item as Transition;
                if (item.RowVersion == 0)
                {
                   // item.Id = trans.GenerateKey("Transition");
                }
                //为防止数据不一致，在新增记录到数据库时，将RowVersion字段固定赋值为1，而不从对象中直接获取属性，在插入成功后再将对象RowVersion属性值设为1
                sql = "INSERT INTO xfTransition(Id, Type, Label, BizRule, FromActivityId, ToActivityId, Invalid, RowVersion) VALUES(@Id, @Type, @Label, @BizRule, @FromActivityId, @ToActivityId, @Invalid, 1)";
                trans.Connection.Execute(sql, transition, trans);
                transition.RowVersion = 1;
                handled = true;
            }
            else
            {
                base.Insert(trans, item, ref handled);
            }
        }

        public override void Update<T>(IDbTransaction trans, T item, ref bool handled)
        {
            string sql;
            Type type = item.GetType();

            if (type == typeof(WorkActivity))//工作活动
            {
                //先调用基类的Update方法
                base.Update<T>(trans, item, ref handled);
                //再将当前活动类特有的属性更新到数据库中
                var activity = item as WorkActivity;
                handled = true;
            }
            else if (type == typeof(Workitem))//工作项
            {
                var workitem = item as Workitem;
                //为防止数据不一致，在更新记录到数据库时，先在SQL脚本中判断RowVersion字段值是否与内存中的值一致，并将RowVersion字段值增1，更新成功后再将对象RowVersion属性值增1
                sql = "UPDATE xfWorkitem SET ActivityId=@ActivityId, Readonly=@Readonly, Action=@Action, EntryTime=@EntryTime, LeaveTime=@LeaveTime, Invalid=@Invalid, RowVersion=RowVersion+1 WHERE Id=@Id AND RowVersion=@RowVersion";
                trans.Connection.Execute(sql, workitem, trans);
                workitem.RowVersion++;
                handled = true;
            }
            //base.Update<T>(trans, item, ref handled);
        }
    }

}
